package com.juejin.www.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.juejin.www.dao.CommentDao;
import com.juejin.www.dao.LikeDao;
import com.juejin.www.dao.UserDao;
import com.juejin.www.model.DO.Comment;
import com.juejin.www.model.DTO.CommentDTO;
import com.juejin.www.model.DTO.UserDTO;
import com.juejin.www.model.VO.CommentVO;
import com.juejin.www.service.CommentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Jacky
 */
@Service
public class CommentServiceImpl implements CommentService {
    
    @Autowired
    private CommentDao commentDao;

    @Autowired
    private UserDao userDao;

    @Autowired
    private LikeDao likeDao;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(CommentDTO commentDTO) {
        Integer beCommentedItemId;
        Integer beCommentedItemType;
        if(commentDTO.getBeCommentedType()!=3){
            beCommentedItemId=commentDTO.getBeCommentedId();
            beCommentedItemType=commentDTO.getBeCommentedType();
        }else {
            beCommentedItemId=commentDao.getBeCommented(commentDTO.getBeCommentedId()).getBeCommentedItem();
            beCommentedItemType=commentDao.getBeCommented(commentDTO.getBeCommentedId()).getBeCommentedItem();
        }
        Comment comment = new Comment(null,
                commentDTO.getBeCommentedId(),
                commentDTO.getBeCommentedType(),
                beCommentedItemId,
                beCommentedItemType,
                commentDTO.getAuthorId(),
                commentDTO.getContent(),
                0,
                0,
                LocalDateTime.now(),
                LocalDateTime.now());
        commentDao.add(comment);

        if(commentDTO.getBeCommentedType()==1){
            commentDao.addArticleCommentCount(commentDTO.getBeCommentedId());
            if(stringRedisTemplate.opsForValue().get("article:"+commentDTO.getBeCommentedId())!=null){
                stringRedisTemplate.delete("article:"+commentDTO.getBeCommentedId());
            }
            if(stringRedisTemplate.opsForValue().get("comment:1:"+commentDTO.getBeCommentedId())!=null){
                stringRedisTemplate.delete("comment:1:"+commentDTO.getBeCommentedId());
            }
        }else if(commentDTO.getBeCommentedType()==2){
            commentDao.addBoilingPointCommentCount(commentDTO.getBeCommentedId());
            if(stringRedisTemplate.opsForValue().get("comment:2:"+commentDTO.getBeCommentedId())!=null){
                stringRedisTemplate.delete("comment:2:"+commentDTO.getBeCommentedId());
            }
        }else {
            CommentDTO beCommented = commentDao.getBeCommented(commentDTO.getBeCommentedId());
            if(beCommented.getBeCommentedType()==1){
                commentDao.addArticleCommentCount(beCommented.getBeCommentedId());
                if(stringRedisTemplate.opsForValue().get("article:"+beCommented.getBeCommentedId())!=null){
                    stringRedisTemplate.delete("article:"+beCommented.getBeCommentedId());
                }
                if(stringRedisTemplate.opsForValue().get("comment:1:"+beCommented.getBeCommentedId())!=null){
                    stringRedisTemplate.delete("comment:1:"+beCommented.getBeCommentedId());
                }
            }else if(beCommented.getBeCommentedType()==2){
                commentDao.addBoilingPointCommentCount(beCommented.getBeCommentedId());
                if(stringRedisTemplate.opsForValue().get("comment:2:"+beCommented.getBeCommentedId())!=null){
                    stringRedisTemplate.delete("comment:2:"+beCommented.getBeCommentedId());
                }
            }
            commentDao.addCommentReplyCount(commentDTO.getBeCommentedId());
            if(stringRedisTemplate.opsForValue().get("comment:3:"+beCommented.getBeCommentedId())!=null){
                stringRedisTemplate.delete("comment:3:"+beCommented.getBeCommentedId());
            }
        }
    }

    @Override
    public List<CommentVO> getComments(Integer beCommentedId, Integer beCommentedType, Integer uid) {
        String key = "comment:"+beCommentedType+":"+beCommentedId;
        String cacheValue = stringRedisTemplate.opsForValue().get(key);
        List<CommentDTO> comments;
        if(cacheValue!=null){
            comments= JSON.parseArray(cacheValue,CommentDTO.class);
        }else {
            comments = commentDao.getComments(beCommentedId, beCommentedType);
            stringRedisTemplate.opsForValue().set(key, JSONObject.toJSONString(comments));
        }

        List<CommentVO> commentVOS = comments.stream()
                .map(comment -> {
                    UserDTO author = userDao.getById(comment.getAuthorId());
                    Boolean isLiked=false;
                    if(uid==null){
                        isLiked=false;
                    }else if(likeDao.checkLike(comment.getId(),3,uid)>0){
                        isLiked=true;
                    }
                    return new CommentVO(
                            comment.getId(),
                            comment.getContent(),
                            author.getName(),
                            comment.getAuthorId(),
                            comment.getLikeCount(),
                            comment.getReplyCount(),
                            comment.getCreateTime(),
                            isLiked
                    );
                })
                .collect(Collectors.toList());
        return commentVOS;
    }

    @Override
    public void deleteComment(Integer id) {
        String key = "comment:"+commentDao.getBeCommented(id).getBeCommentedType()+":"+commentDao.getBeCommented(id).getBeCommentedId();
        String cacheValue = stringRedisTemplate.opsForValue().get(key);
        if(cacheValue!=null){
            stringRedisTemplate.delete(key);
        }
        commentDao.deleteComment(id);
    }
}
